#ifndef _BIGNUM_H
#define _BIGNUM_H

#include <stdint.h>

/*
 *  用来存储大整数的类型。
 *  数字以小端序存储在 data 内，其长度存储在 size 中。
 *  在 data 中存储的数字可能有前导零，因此不能简单地通过 size 的大小来判断数字的大小。
 *  例子：
 *  0x112233445566 存储为 66 55 44 33 22 11 (size = 6)
 */
typedef struct {
    int32_t size;
    uint8_t* data;
} bignum_t;

extern bignum_t bignum_zero;
extern bignum_t bignum_one;
extern bignum_t bignum_two;
extern bignum_t bignum_three;
extern bignum_t bignum_four;
extern bignum_t bignum_five;
extern bignum_t bignum_six;

void bignum_free(bignum_t* num);
int bignum_compare(bignum_t* a, bignum_t* b);
int bignum_hibit(bignum_t* a);
void bignum_swap(bignum_t* a, bignum_t* b);
void bignum_cpy(bignum_t* a, bignum_t* b);
void bignum_add(bignum_t* p, bignum_t* q, bignum_t* res);
void bignum_inc(bignum_t* p, bignum_t* q);
void bignum_sub(bignum_t* p, bignum_t* q, bignum_t* res);
void bignum_dec(bignum_t* p, bignum_t* q);
void bignum_lshift(bignum_t* bn, int32_t n, bignum_t* res);
void bignum_lshift_1(bignum_t* bn);
void bignum_rshift(bignum_t* bn, int32_t n, bignum_t* res);
void bignum_rshift_1(bignum_t* bn);
void bignum_mul(bignum_t* p, bignum_t* q, bignum_t* res);
void bignum_div(bignum_t* a, bignum_t* b, bignum_t* quotient, bignum_t* remainder);
void bignum_self_div(bignum_t* a, bignum_t* b);
void bignum_pow_mod(bignum_t* p, uint32_t e, bignum_t* n, bignum_t* res);
void bignum_pow_mod_bignum(bignum_t* p, bignum_t* e, bignum_t* n, bignum_t* res);
void bignum_mod(bignum_t* a, bignum_t* b, bignum_t* res);
void bignum_self_mod(bignum_t* a, bignum_t* b);
void bignum_set32(int32_t a, bignum_t* res);
void bignum_trim(bignum_t* num);
void bignum_gcd(bignum_t* a, bignum_t* b, bignum_t* res);
int bignum_mod_inv(bignum_t* a, bignum_t* mod, bignum_t* res);

#endif
